//=========================================================================
// Copyright (C) 2024 The C++ Component Model(COMO) Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//=========================================================================

/**
 * Declare all pmalloc related functions
 */

#ifndef __PMINTERNAL_H__
#define __PMINTERNAL_H__

#include "cots_config.h"
#include "pmalloc.h"

#define PMALLOC_MAGIC "pmalloc_bigdata1"
#define PMALLOC_MAGIC_SIZE 32
#define PMALLOC_VERSION static_cast<unsigned char>(2)

#define INT_BIT (CHAR_BIT * sizeof(int))
#define SIZET_BIT (CHAR_BIT * sizeof(size_t))

/**
 * 1M = 1 * 1024 * 1024, 20 bits
 */
#define BLOCKLOG ((SIZET_BIT > 32) ?  20 : ((SIZET_BIT > 16) ? 12 : 9))

#define FINAL_FREE_BLOCKS static_cast<size_t>(2)

#define MALLOC_SEARCH_START mdp->mblkinfosearchindex

// 内存块组织结构：inuse & free
// 理解为chunk比较合理
typedef union {
    struct {
        int fragtype;
        union {
            struct {
                size_t nfreefrags;
                size_t firstfragidxinlist;
            } frag;
            size_t sizeinblock;
        } info;
    } inuse;
    struct {
        size_t size;
        size_t next;
        size_t prev;
    } free;
} malloc_info;

struct alignlist {
    struct alignlist *next;
    void             *alignedaddr;
    void             *unalignedaddr;
};

// 链表结构
struct list {
    struct list *next;
    struct list *prev;
};

// 当前所管理的内存池使用情况
struct mempoolstats {
    size_t bytes_total;
    size_t chunks_used;
    size_t bytes_used;
    size_t chunks_free;
    size_t bytes_free;
};

struct mdesc {
    void *(*morespace)(struct mdesc *, ptrdiff_t);  // 拓展空间函数指针 morespace
    void (*abortfunc)(void *, void *, int);

    char            magicwords[PMALLOC_MAGIC_SIZE]; // magicwords
    unsigned int    headersize;                     // 管理结构header的大小
    unsigned char   version;                        // 当前版本
    unsigned int    flags;                          // 标志位
    int             saved_errno;                    // 错误码
    size_t          mblkinfosize;                   // 当前管理内存块的管理结构数量
    char           *mblkinfobase;                   // 内存块管理结构的起始地址
    size_t          mblkinfosearchindex;            // 从内存块管理结构开始搜索的index
    size_t          mblkinfoidxlimit;               // 当前管理内存块的管理结构数量上限
    malloc_info    *mblkinfo;                       // 管理内存块的结构
    struct mempoolstats mblkstats;                  // 内存池使用情况
    struct list         fragblockhead[BLOCKLOG];
    struct alignlist   *aligned_blocks;
    char           *mempoolbase;                    // 内存起始地址
    char           *watermarkpos;                   // 当前所占用的内存上界
    char           *limitpos;                       // 理论的内存上限
    int             mappingfd;                      // 对应打开的文件描述符
    void           *persistkeys[PMALLOC_KEYS];      // Key-Value结构
    int             persistValuesSize[PMALLOC_KEYS];
    int             partitionNo;                    // 当前分区编号

    bool            fixedSize;                      // 固定内存大小，初始化时指定
};

#ifdef __cplusplus
extern "C"
{
#endif

extern struct mdesc *__pmalloc_default_mdp;  // 默认内存池管理结构

extern void __pmalloc_free(struct mdesc *mdp, void *addr);
extern void *__pmalloc_map_morespace(struct mdesc *mdp, const ptrdiff_t size);
extern void *__pmalloc_remap_mempool(struct mdesc *mdp);
extern void *pmalloc_attach(int fd, void *baseaddr, const size_t initial_size, bool fixSized);
extern void *pmalloc_detach(void *md);
extern void rebase_mdesc_infos(struct mdesc *mdp, void *e_addr, void *o_addr);

#ifdef __cplusplus
}
#endif

#endif // __PMINTERNAL_H__
